﻿using Microsoft.AspNet.TestHost;
using Microsoft.Extensions.Configuration;
using Newtonsoft.Json;
using Newtonsoft.Json.Linq;
using Plugin.Connectivity;
using Sino.CapacityCloud.Tests.Fixtures;
using Sino.CapacityCloud.Tests.Services;
using Sino.CapacityCloud.Web;
using Sino.CapacityCloud.WebApi.Client;
using Sino.WebApi.Framework.Protocol;
using Sino.WebApi.Framework.Responses;
using System;
using System.Net;
using System.Net.Http;
using System.Threading.Tasks;
using Xunit;

namespace Sino.CapacityCloud.Tests.ApiControllers
{

    [Collection("Database collection")]
    public class WebApiControllerTestBase
        : IDisposable
    {

        protected readonly TestServer _server;

        protected readonly CapacityCloudRestfulApiClientEx _client;

        public IConfigurationRoot Configuration { get; private set; }

        public string AdministratorPhoneNumber { get; protected set; }

        public DatabaseFixture Database { get; protected set; }

        public WebApiControllerTestBase(DatabaseFixture fixture)
        {
            JsonConvert.DefaultSettings = () => new JsonSerializerSettings() { ReferenceLoopHandling = ReferenceLoopHandling.Serialize };

            this.Database = fixture;

            var builder = new ConfigurationBuilder()
               .AddJsonFile("appsettings.json")
               .AddEnvironmentVariables();

            this.Configuration = builder.Build();

            this.AdministratorPhoneNumber = this.Configuration["Administrator:DefaultAdminPhoneNumber"];

            //if (File.Exists("CapacityCloudWeb.db"))
            //{
            //    File.Delete("CapacityCloudWeb.db");
            //    File.Copy("./Resources/CapacityCloudWebSeed", "CapacityCloudWeb.db", true);
            //}

            this._server = new TestServer(TestServer.CreateBuilder().UseStartup<TestStartup>());
            this._client = new CapacityCloudRestfulApiClientEx(this._server.CreateClient().AcceptJson(),
                CrossConnectivity.Current, ConfigurationOptions.LoadSettings(typeof(CapacityCloudRestfulApiClient).Assembly, "Debug"));
        }

        protected async Task LoginAsync()
        {
            var response = await this._client.LoginAsync(this.AdministratorPhoneNumber, "2020");
            var token = response?.Info?.Token;
            Assert.False(string.IsNullOrWhiteSpace(token));
        }

        protected async Task<ResponsePack<TResponse>> AssertResponse<TResponse>(HttpResponseMessage response) where TResponse : ResponseBase
        {
            Assert.True(response.StatusCode == HttpStatusCode.OK);
            var str = await response.Content.ReadAsStringAsync();
            Assert.False(string.IsNullOrEmpty(str));
            Console.WriteLine($"Response:\n{str}");
            var result = JObject.Parse(str).ToObject<ResponsePack<TResponse>>();
            Assert.False(result.Error != null, $"Code: {result.Error?.Code}, Message: {result.Error?.Message ?? ""}");
            return result;
        }

        #region IDisposable
        // Flag: Has Dispose already been called?
        private bool disposed = false;

        // Public implementation of Dispose pattern callable by consumers.
        public void Dispose()
        {
            Dispose(true);
            GC.SuppressFinalize(this);
        }

        // Protected implementation of Dispose pattern.
        protected virtual void Dispose(bool disposing)
        {
            if (disposed)
                return;

            if (disposing)
            {
                // Free any other managed objects here.
                this._client?.Dispose();
                this._server?.Dispose();
            }

            // Free any unmanaged objects here.
            //
            disposed = true;
        }
        #endregion

    }

}